#ifndef _BSP_SPI_FLASH_
#define	_BSP_SPI_FLASH_
#include "stm32f10x.h"
#include <stdio.h>       //是为了方便使用printf()函数

//在头文件中定义与硬件有关的操作
/*
	编程要点:
				1.初始化目标引脚和端口时钟
				2.使能SPI外设的时钟
				3.配置SPI外设的相关参数，并使能SPI外设
				4.编写基本的SPI按字节收发的函数(突出的是按字节)
				5.编写对FLASH擦除及读写操作的函数(在字节的基础上,是按块)
				6.编写最终的测试函数
*/
/*SPI接口定义-开头*********************************************/
#define				FLASH_SPIx				SPI1
#define				FLASH_SPI_CLOCK_FUN		RCC_APB2PeriphClockCmd
#define				FLASH_SPI_CLOCK_CMD		RCC_APB2Periph_SPI1

/*CS(NSS)引脚片选选普通GPIO即可*/
#define				FLASH_SPI_CS_CLOCK_FUN  RCC_APB2PeriphClockCmd
#define				FLASH_SPI_CS_CLOCK_CMD	RCC_APB2Periph_GPIOA
#define				FLASH_SPI_CS_PORT		GPIOA//(其实是一个结构体类型的指针)
#define				FLASH_SPI_CS_PIN		GPIO_Pin_4

/*SCK引脚***********************/
#define				FLASH_SPI_SCK_CLOCK_FUN  RCC_APB2PeriphClockCmd
#define				FLASH_SPI_SCK_CLOCK_CMD	 RCC_APB2Periph_GPIOA
#define				FLASH_SPI_SCK_PORT		 GPIOA//(其实是一个结构体类型的指针)
#define				FLASH_SPI_SCK_PIN		 GPIO_Pin_5

/*MISO引脚*********************/
#define				FLASH_SPI_MISO_CLOCK_FUN  RCC_APB2PeriphClockCmd
#define				FLASH_SPI_MISO_CLOCK_CMD	 RCC_APB2Periph_GPIOA
#define				FLASH_SPI_MISO_PORT		 GPIOA//(其实是一个结构体类型的指针)
#define				FLASH_SPI_MISO_PIN		 GPIO_Pin_6

/*MOSI引脚*********************/
#define				FLASH_SPI_MOSI_CLOCK_FUN  RCC_APB2PeriphClockCmd
#define				FLASH_SPI_MOSI_CLOCK_CMD	 RCC_APB2Periph_GPIOA
#define				FLASH_SPI_MOSI_PORT		 GPIOA//(其实是一个结构体类型的指针)
#define				FLASH_SPI_MOSI_PIN		 GPIO_Pin_7

/*CS引脚操作宏(为毛这样写)**********************/
#define				FLASH_SPI_CS_LOW()		GPIO_ResetBits(FLASH_SPI_CS_PORT,FLASH_SPI_CS_PIN) 
#define				FLASH_SPI_CS_HIGH()		GPIO_SetBits(FLASH_SPI_CS_PORT,FLASH_SPI_CS_PIN)

/*****************FLASH常用命令,宏定义(根据数据手册得来的)*******************************/
#define			W25X_WriteEnable			0x06
#define			W25X_WriteDisable			0x04
#define			W25X_ReadStatusReg			0x05
#define			W25X_WriteStatusReg			0x01
#define			W25X_ReadData				0x03
#define			W25X_FastReadData           0x0B
#define			W25X_FastReadDual			0x3B
#define			W25X_PageProgram			0x02
#define			W25X_BlockErase				0xD8
#define			W25X_SectorErase			0x20
#define			W25X_ChipErase				0xC7
#define			W25X_PowerDown				0xB9
#define			W25X_ReleasePowerDown		0xAB
#define			W25X_DeviceID				0xAB
#define			W25X_ManufactDeviceID		0x90
#define			W25X_JedecDeviceID			0x9F
#define			sFLASH_ID					0xEF4017   //专指W25Q64
#define			Dummy_Byte					0xFF  //虚字节
#define			WIP_Flag					0x01   //读忙掩码

#define			SPI_FLASH_PerWritePageSize  256     //FLASH写的页大小

/***********通讯等待超时时间(其实是次数)**********************************/
#define	SPI_FLAG_TIMEOUT		((uint32_t)0x1000)    //4096
#define	SPI_LONG_TIMEOUT		((uint32_t)(10*SPI_FLAG_TIMEOUT)) //40960

/****************************************************************************相关信息输出**************************************************************/
#define		SPI_debug

#define		SPI_INFO(fmt,arg...)			printf("<<-SPI-INFO->>"fmt,##arg)                  //printf()函数可以实现字符串的自动拼接  fmt为一个字符串
#define		SPI_ERROR(fmt,arg...)			printf("<<-SPI-ERROR->>"fmt,##arg)             //这个写法很得注意


#ifdef		SPI_debug
#define		SPI_DEBUG(fmt,arg...)			printf("<<-SPI-DEBUG->> LINE[%d]"fmt,__LINE__,##arg)      //##的作用是在arg未穿入参数的时候自动去除##前面的,号
#else
#define		SPI_DEBUG(fmt,arg...)
#endif

void SPI_FLASH_Init(void);
uint8_t	SPI_FLASH_SendByte(uint8_t byte);
uint8_t SPI_FLASH_ReadByte(void);
uint32_t SPI_FLASH_ReadJedecDeviceID(void);
uint32_t SPI_FLASH_ReadDeviceID(void);
 void SPI_FLASH_WriteEnable(void);
  void	SPI_FLASH_WaitForWriteEnd(void);
void	SPI_FLASH_SectorErase(uint32_t SectorAddr);
 void	SPI_FLASH_PageWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
 void SPI_FLASH_BufferWrite(uint8_t * pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
 void SPI_FLASH_BufferRead(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t NumByteToRead);
 

#ifndef		_BSP_SPI_FLASH_C

#endif

#endif

